<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        function Father() {
            this.run = function() {
                console.log('父亲喜欢跑步');
            }
        }
        Father.prototype.work = function() {
            console.log('父亲要工作');
        }

        function Son() {

        }
        // 错误方式，该代码会导致子原型对象指向父原型对象的地址，如果更改子原型对象，则实际更改的是父原型对象。
        // Son.prototype = Father.prototype

        // 使子原型对象指向一个父实例对象，便拥有了父构造函数的方法以及父构造函数的原型对象上的方法
        Son.prototype = new Father();
        // 小问题：上述直接通过对象覆盖了子原型对象，导致了constructor指向的构造函数的改变，需要单独为其赋值
        // console.log(Son.prototype.constructor);
        Son.prototype.constructor = Son


        Son.prototype.exam = function() {
            console.log('孩子要考试');
        }
        var xiaoming = new Son()

        console.log(xiaoming);

        // 打印父原型对象，正确的结果不应该包含子原型对象的方法
        console.log(Father.prototype);

        // 验证是否实现了继承
        xiaoming.work()
        xiaoming.run()

        // 整个过程的描述：
        // 1.先在xiaoming对象上找work()和run()
        // 2.若找不到则在xiaoming的__proto__,即父实例对象身上找work()和run()
        // 3.若还是找不到则在父构造函数的原型对象上找，最终找到了work()和run()

        // 通过构造函数和原型对象实现继承的原理：（充分利用了原型链）
        // 1.子对象在找不到方法时会去原型对象上找方法，
        // 2.让子构造函数的原型对象指向父实例对象，则相当于子对象会去父实例对象上找方法。
        // 3.若在父实例对象上找不到方法，则会去父构造函数的原型对象上找这个方法，只要找到了方法则说明继承了父方法。
    </script>
</body>

</html>